/*********************************************************************************
 *      Copyright:  (C) 2022 xiezongyi<1764417007@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  tlv_client.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(11/08/22)
 *         Author:  xiezongyi <1764417007@qq.com>
 *      ChangeLog:  1, Release initial version on "11/08/22 12:27:53"
 *                 
 ********************************************************************************/
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "CRC.h"
#include "tlv_client.h"

/*  Packet 3 TLV message together: with SN, temperature, date&time */
int packtlv_msg(tlv_buf_t *tlv, char *sn, u_int16_t temp, struct tm *tm)
{
    int               rv;

    if( !tlv )
    {
        printf("Invalid input arguments\n");
        return -1;
    }

    memset(tlv->buf, 0, sizeof(tlv->buf)); /* clear data in buffer */
    tlv->size = sizeof(tlv->buf); /* buffer free space size */
    tlv->len = 0; /* buffer data length */

    if( sn )
    {
        rv = packtlv_sn(&tlv->buf[tlv->len], tlv->size, sn);
        if( rv > 0 )
        {
            tlv->len += rv;
            tlv->size -= rv;
        }
    }

    if( temp )
    {
        rv = packtlv_temp(&tlv->buf[tlv->len], tlv->size, temp);
        if( rv > 0 )
        {
            tlv->len += rv;
            tlv->size -= rv;
        }
    }

    if( tm )
    {
        rv = packtlv_time(&tlv->buf[tlv->len], tlv->size, tm);
        if( rv > 0 )
        {
            tlv->len += rv;
            tlv->size -= rv;
        }
    }

    return 0;
}

int packtlv_temp(char *buf, int size, u_int16_t temp)
{
    unsigned short      crc16 = 0;
    int                 pack_len = 0;
    int                 ofset = 0; /* index position for the buf */

    if(!buf || size<TLV_FIXED_SIZE+2 )
    {
        printf("Invalid input arguments\n");
        return 0;
    }

    /*+-------------------------+
     *|   1.fill packet Header  |
     *+-------------------------+*/

    buf[ofset] = PACK_HEADER;
    ofset += 1;

    /*+-------------------------+
     *|   2.fill packet Tag     |
     *+-------------------------+*/

    buf[ofset] = TAG_TEMP;
    ofset += 1;

    /*+-------------------------+
     *|   3.fill packet Length  |
     *+-------------------------+*/
    /* termperature message get 2B payload data */

    pack_len = TLV_FIXED_SIZE + 2;
    buf[ofset] = pack_len;
    ofset += 1;

    /*+-------------------------+
     *|   4.fill packet Value   |
     *+-------------------------+*/

    /* temperature get 2 bytes, byte[0]:integer part, byte[1]:fractional part  */
    memcpy(&buf[ofset], &temp, 2);
    ofset += 2;

    /*+-------------------------+
     *|   5.fill packet CRC     |
     *+-------------------------+*/

    /* Calc CRC16 checksum value from Packet Head(buf[0]) ~ Value(buf[ofset]) */
    crc16 = crc16_maxim(buf, ofset);

    /* Append the 2 Bytes CRC16 checksum value into the last two bytes in packet buffer */
    unsigned char crc1 = crc16 >> 8; //取高8位
    unsigned char crc2 = crc16 & 0xff; //取低8位
    memcpy(&buf[ofset], &crc1, 1);
    ofset += 1;
    memcpy(&buf[ofset], &crc2, 1);
    ofset += 1;
    /* ofset value is the TLV packet length  */
    return ofset;
}

int packtlv_time(char *buf, int size, struct tm *tm)
{
    unsigned short      crc16 = 0;
    int                 pack_len = 0;
    int                 ofset = 0; /* index position for the buf */

    if(!buf || size<TLV_FIXED_SIZE+6 )
    {
        printf("Invalid input arguments\n");
        return 0;
    }

    /*+-------------------------+
     *|   1.fill packet Header  |
     *+-------------------------+*/

    buf[ofset] = PACK_HEADER;
    ofset += 1;

    /*+-------------------------+
     *|   2.fill packet Tag     |
     *+-------------------------+*/

    buf[ofset] = TAG_TIME;
    ofset += 1;

    /*+-------------------------+
     *|   3.fill packet Length  |
     *+-------------------------+*/

    /* date time message get 6B payload data */
    pack_len = TLV_FIXED_SIZE + 6;
    buf[ofset] = pack_len;
    ofset += 1;

    /*+-------------------------+
     *|   4.fill packet Value   |
     *+-------------------------+*/

    buf[ofset++] = tm->tm_year-100; /* tm_year is since 1900, we change it it to 2000 */
    buf[ofset++] = tm->tm_mon+1;    /* tm_mon is from 0~11  */
    buf[ofset++] = tm->tm_mday;
    buf[ofset++] = tm->tm_hour;
    buf[ofset++] = tm->tm_min;
    buf[ofset++] = tm->tm_sec;

	/*+-------------------------+
     *|   5.fill packet CRC     |
     *+-------------------------+*/

    /* Calc CRC16 checksum value from Packet Head(buf[0]) ~ Value(buf[ofset]) */
    crc16 = crc16_maxim(buf, ofset);

    /* Append the 2 Bytes CRC16 checksum value into the last two bytes in packet buffer */
    unsigned char crc1 = crc16 >> 8; //取高8位
    unsigned char crc2 = crc16 & 0xff; //取低8位
    memcpy(&buf[ofset], &crc1, 1);
    ofset += 1;
    memcpy(&buf[ofset], &crc2, 1);
    ofset += 1;

    /* ofset value is the TLV packet length  */
    return ofset;
}

int packtlv_sn(char *buf, int size, char *sn)
{
    unsigned short      crc16 = 0;
    int                 payload_len = 0;
    int                 pack_len = 0;
    int                 ofset = 0; /* index position for the buf */
    if(!buf || size<TLV_MIN_SIZE )
    {
        printf("Invalid input arguments\n");
        return 0;
    }

    /*+-------------------------+
     *|   1.fill packet Header  |
     *+-------------------------+*/
    buf[ofset] = PACK_HEADER;
    ofset += 1;

    /*+-------------------------+
     *|   2.fill packet Tag     |
     *+-------------------------+*/
    buf[ofset] = TAG_SN;
    ofset += 1;

    /*+-------------------------+
     *|   3.fill packet Length  |
     *+-------------------------+*/

    /* $sn too long maybe result buffer overflow, so we need check the buffer
     * is large enuf or not. If not enuf we will truncate $sn string
     */
    if( strlen(sn) <= size-TLV_FIXED_SIZE )
        payload_len = strlen(sn);
    else
        payload_len = size-TLV_FIXED_SIZE;

    /*  TLV packet length is SN length+5Byte () */
    pack_len = payload_len + TLV_FIXED_SIZE;

    buf[ofset] = pack_len;
    ofset += 1;

    /*+-------------------------+
     *|   4.fill packet Value   |
     *+-------------------------+*/
    memcpy(&buf[ofset], sn, payload_len);
    ofset += payload_len;

    /*+-------------------------+
     *|   5.fill packet CRC     |
     *+-------------------------+*/

    /* Calc CRC16 checksum value from Packet Head(buf[0]) ~ Value(buf[ofset]) */
    crc16 = crc16_maxim(buf, ofset);

    /* Append the 2 Bytes CRC16 checksum value into the last two bytes in packet buffer */
    unsigned char crc1 = crc16 >> 8; //取高8位
    unsigned char crc2 = crc16 & 0xff; //取低8位
    memcpy(&buf[ofset], &crc1, 1);
    ofset += 1;
    memcpy(&buf[ofset], &crc2, 1);
    ofset += 1;

    /* ofset value is the TLV packet length  */
    return ofset;
}

void dump_buf(char *data, int len)
{
    printf("Write %d bytes data from client:\n", len);
    for(int i=0; i<len; i++)
    {
        printf("0x%02X", data[i]);
    }
    printf("\n");
}

